home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / dev / gg / ncurses-5.3.lha / ncurses-5.3 / progs / tput.c < prev    next >
C/C++ Source or Header  |  2002-10-24  |  11KB  |  429 lines

  1. /****************************************************************************
  2.  * Copyright (c) 1998,1999,2000,2001 Free Software Foundation, Inc.         *
  3.  *                                                                          *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a  *
  5.  * copy of this software and associated documentation files (the            *
  6.  * "Software"), to deal in the Software without restriction, including      *
  7.  * without limitation the rights to use, copy, modify, merge, publish,      *
  8.  * distribute, distribute with modifications, sublicense, and/or sell       *
  9.  * copies of the Software, and to permit persons to whom the Software is    *
  10.  * furnished to do so, subject to the following conditions:                 *
  11.  *                                                                          *
  12.  * The above copyright notice and this permission notice shall be included  *
  13.  * in all copies or substantial portions of the Software.                   *
  14.  *                                                                          *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
  16.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
  17.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
  18.  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
  19.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
  20.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
  21.  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
  22.  *                                                                          *
  23.  * Except as contained in this notice, the name(s) of the above copyright   *
  24.  * holders shall not be used in advertising or otherwise to promote the     *
  25.  * sale, use or other dealings in this Software without prior written       *
  26.  * authorization.                                                           *
  27.  ****************************************************************************/
  28.  
  29. /****************************************************************************
  30.  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
  31.  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
  32.  ****************************************************************************/
  33.  
  34. /*
  35.  * tput.c -- shellscript access to terminal capabilities
  36.  *
  37.  * by Eric S. Raymond <esr@snark.thyrsus.com>, portions based on code from
  38.  * Ross Ridge's mytinfo package.
  39.  */
  40.  
  41. #include <progs.priv.h>
  42.  
  43. #if !PURE_TERMINFO
  44. #include <termsort.c>
  45. #endif
  46. #include <transform.h>
  47.  
  48. MODULE_ID("$Id: tput.c,v 1.31 2002/07/20 19:09:47 tom Exp $")
  49.  
  50. #define PUTS(s)        fputs(s, stdout)
  51. #define PUTCHAR(c)    putchar(c)
  52. #define FLUSH        fflush(stdout)
  53.  
  54. typedef enum {
  55.     Numbers = 0
  56.     ,Num_Str
  57.     ,Num_Str_Str
  58. } TParams;
  59.  
  60. static char *prg_name;
  61. static bool is_init = FALSE;
  62. static bool is_reset = FALSE;
  63.  
  64. static void
  65. quit(int status, const char *fmt,...)
  66. {
  67.     va_list argp;
  68.  
  69.     va_start(argp, fmt);
  70.     vfprintf(stderr, fmt, argp);
  71.     fprintf(stderr, "\n");
  72.     va_end(argp);
  73.     exit(status);
  74. }
  75.  
  76. static void
  77. usage(void)
  78. {
  79.     fprintf(stderr, "usage: %s [-V] [-S] [-T term] capname\n", prg_name);
  80.     exit(EXIT_FAILURE);
  81. }
  82.  
  83. static void
  84. check_aliases(const char *name)
  85. {
  86.     is_init = (strcmp(name, PROG_INIT) == 0);
  87.     is_reset = (strcmp(name, PROG_RESET) == 0);
  88. }
  89.  
  90. /*
  91.  * Lookup the type of call we should make to tparm().  This ignores the actual
  92.  * terminfo capability (bad, because it is not extensible), but makes this
  93.  * code portable to platforms where sizeof(int) != sizeof(char *).
  94.  *
  95.  * FIXME: If we want extensibility, analyze the capability string as we do
  96.  * in tparm() to decide how to parse the varargs list.
  97.  */
  98. static TParams
  99. tparm_type(const char *name)
  100. {
  101. #define TD(code, longname, ti, tc) {code,longname},{code,ti},{code,tc}
  102.     TParams result = Numbers;
  103.     /* *INDENT-OFF* */
  104.     static const struct {
  105.     TParams code;
  106.     const char *name;
  107.     } table[] = {
  108.     TD(Num_Str,    "pkey_key",    "pfkey",    "pk"),
  109.     TD(Num_Str,    "pkey_local",    "pfloc",    "pl"),
  110.     TD(Num_Str,    "pkey_xmit",    "pfx",        "px"),
  111.     TD(Num_Str,    "plab_norm",    "pln",        "pn"),
  112.     TD(Num_Str_Str, "pkey_plab",    "pfxl",        "xl"),
  113.     };
  114.     /* *INDENT-ON* */
  115.  
  116.     unsigned n;
  117.     for (n = 0; n < SIZEOF(table); n++) {
  118.     if (!strcmp(name, table[n].name)) {
  119.         result = table[n].code;
  120.         break;
  121.     }
  122.     }
  123.     return result;
  124. }
  125.  
  126. static int
  127. exit_code(int token, int value)
  128. {
  129.     int result = 99;
  130.  
  131.     switch (token) {
  132.     case BOOLEAN:
  133.     result = !value;    /* TRUE=0, FALSE=1 */
  134.     break;
  135.     case NUMBER:
  136.     result = 0;        /* always zero */
  137.     break;
  138.     case STRING:
  139.     result = value;        /* 0=normal, 1=missing */
  140.     break;
  141.     }
  142.     return result;
  143. }
  144.  
  145. static int
  146. tput(int argc, char *argv[])
  147. {
  148.     NCURSES_CONST char *name;
  149.     char *s;
  150.     int i, j, c;
  151.     int status;
  152.     FILE *f;
  153.     int token = UNDEF;
  154.  
  155.     if ((name = argv[0]) == 0)
  156.     name = "";
  157.     check_aliases(name);
  158.     if (is_reset || is_init) {
  159.     if (init_prog != 0) {
  160.         system(init_prog);
  161.     }
  162.     FLUSH;
  163.  
  164.     if (is_reset && reset_1string != 0) {
  165.         PUTS(reset_1string);
  166.     } else if (init_1string != 0) {
  167.         PUTS(init_1string);
  168.     }
  169.     FLUSH;
  170.  
  171.     if (is_reset && reset_2string != 0) {
  172.         PUTS(reset_2string);
  173.     } else if (init_2string != 0) {
  174.         PUTS(init_2string);
  175.     }
  176.     FLUSH;
  177.  
  178. #ifdef set_lr_margin
  179.     if (set_lr_margin != 0) {
  180.         PUTS(tparm(set_lr_margin, 0, columns - 1));
  181.     } else
  182. #endif
  183. #ifdef set_left_margin_parm
  184.         if (set_left_margin_parm != 0
  185.         && set_right_margin_parm != 0) {
  186.         PUTS(tparm(set_left_margin_parm, 0));
  187.         PUTS(tparm(set_right_margin_parm, columns - 1));
  188.     } else
  189. #endif
  190.         if (clear_margins != 0
  191.         && set_left_margin != 0
  192.         && set_right_margin != 0) {
  193.         PUTS(clear_margins);
  194.         if (carriage_return != 0) {
  195.         PUTS(carriage_return);
  196.         } else {
  197.         PUTCHAR('\r');
  198.         }
  199.         PUTS(set_left_margin);
  200.         if (parm_right_cursor) {
  201.         PUTS(tparm(parm_right_cursor, columns - 1));
  202.         } else {
  203.         for (i = 0; i < columns - 1; i++) {
  204.             PUTCHAR(' ');
  205.         }
  206.         }
  207.         PUTS(set_right_margin);
  208.         if (carriage_return != 0) {
  209.         PUTS(carriage_return);
  210.         } else {
  211.         PUTCHAR('\r');
  212.         }
  213.     }
  214.     FLUSH;
  215.  
  216.     if (init_tabs != 8) {
  217.         if (clear_all_tabs != 0 && set_tab != 0) {
  218.         for (i = 0; i < columns - 1; i += 8) {
  219.             if (parm_right_cursor) {
  220.             PUTS(tparm(parm_right_cursor, 8));
  221.             } else {
  222.             for (j = 0; j < 8; j++)
  223.                 PUTCHAR(' ');
  224.             }
  225.             PUTS(set_tab);
  226.         }
  227.         FLUSH;
  228.         }
  229.     }
  230.  
  231.     if (is_reset && reset_file != 0) {
  232.         f = fopen(reset_file, "r");
  233.         if (f == 0) {
  234.         quit(4 + errno, "Can't open reset_file: '%s'", reset_file);
  235.         }
  236.         while ((c = fgetc(f)) != EOF) {
  237.         PUTCHAR(c);
  238.         }
  239.         fclose(f);
  240.     } else if (init_file != 0) {
  241.         f = fopen(init_file, "r");
  242.         if (f == 0) {
  243.         quit(4 + errno, "Can't open init_file: '%s'", init_file);
  244.         }
  245.         while ((c = fgetc(f)) != EOF) {
  246.         PUTCHAR(c);
  247.         }
  248.         fclose(f);
  249.     }
  250.     FLUSH;
  251.  
  252.     if (is_reset && reset_3string != 0) {
  253.         PUTS(reset_3string);
  254.     } else if (init_2string != 0) {
  255.         PUTS(init_2string);
  256.     }
  257.     FLUSH;
  258.     return 0;
  259.     }
  260.  
  261.     if (strcmp(name, "longname") == 0) {
  262.     PUTS(longname());
  263.     return 0;
  264.     }
  265. #if !PURE_TERMINFO
  266.     {
  267.     const struct name_table_entry *np;
  268.  
  269.     if ((np = _nc_find_entry(name, _nc_get_hash_table(1))) != 0)
  270.         switch (np->nte_type) {
  271.         case BOOLEAN:
  272.         if (bool_from_termcap[np->nte_index])
  273.             name = boolnames[np->nte_index];
  274.         break;
  275.  
  276.         case NUMBER:
  277.         if (num_from_termcap[np->nte_index])
  278.             name = numnames[np->nte_index];
  279.         break;
  280.  
  281.         case STRING:
  282.         if (str_from_termcap[np->nte_index])
  283.             name = strnames[np->nte_index];
  284.         break;
  285.         }
  286.     }
  287. #endif
  288.  
  289.     if ((status = tigetflag(name)) != -1) {
  290.     return exit_code(BOOLEAN, status);
  291.     } else if ((status = tigetnum(name)) != CANCELLED_NUMERIC) {
  292.     (void) printf("%d\n", status);
  293.     return exit_code(NUMBER, 0);
  294.     } else if ((s = tigetstr(name)) == CANCELLED_STRING) {
  295.     quit(4, "%s: unknown terminfo capability '%s'", prg_name, name);
  296.     } else if (s != ABSENT_STRING) {
  297.     token = STRING;
  298.     if (argc > 1) {
  299.         int k;
  300.         int numbers[10];
  301.         char *strings[10];
  302.  
  303.         /* Nasty hack time. The tparm function needs to see numeric
  304.          * parameters as numbers, not as pointers to their string
  305.          * representations
  306.          */
  307.  
  308.         for (k = 1; k < argc; k++) {
  309.         char *tmp = 0;
  310.         strings[k] = argv[k];
  311.         numbers[k] = strtol(argv[k], &tmp, 0);
  312.         if (tmp == 0 || *tmp != 0)
  313.             numbers[k] = 0;
  314.         }
  315.         for (k = argc; k <= 9; k++) {
  316.         numbers[k] = 0;
  317.         strings[k] = 0;
  318.         }
  319.  
  320.         switch (tparm_type(name)) {
  321.         case Num_Str:
  322.         s = tparm(s, numbers[1], strings[2]);
  323.         break;
  324.         case Num_Str_Str:
  325.         s = tparm(s, numbers[1], strings[2], strings[3]);
  326.         break;
  327.         default:
  328.         s = tparm(s,
  329.               numbers[1], numbers[2], numbers[3],
  330.               numbers[4], numbers[5], numbers[6],
  331.               numbers[7], numbers[8], numbers[9]);
  332.         break;
  333.         }
  334.     }
  335.  
  336.     /* use putp() in order to perform padding */
  337.     putp(s);
  338.     return exit_code(STRING, 0);
  339.     }
  340.     return exit_code(STRING, 1);
  341. }
  342.  
  343. int
  344. main(int argc, char **argv)
  345. {
  346.     char *term;
  347.     int errret;
  348.     bool cmdline = TRUE;
  349.     int c;
  350.     char buf[BUFSIZ];
  351.     int result = 0;
  352.     int err;
  353.  
  354.     check_aliases(prg_name = _nc_rootname(argv[0]));
  355.  
  356.     term = getenv("TERM");
  357.  
  358.     while ((c = getopt(argc, argv, "ST:V")) != EOF) {
  359.     switch (c) {
  360.     case 'S':
  361.         cmdline = FALSE;
  362.         break;
  363.     case 'T':
  364.         use_env(FALSE);
  365.         term = optarg;
  366.         break;
  367.     case 'V':
  368.         puts(curses_version());
  369.         return EXIT_SUCCESS;
  370.     default:
  371.         usage();
  372.         /* NOTREACHED */
  373.     }
  374.     }
  375.  
  376.     /*
  377.      * Modify the argument list to omit the options we processed.
  378.      */
  379.     if (is_reset || is_init) {
  380.     if (optind-- < argc) {
  381.         argc -= optind;
  382.         argv += optind;
  383.     }
  384.     argv[0] = prg_name;
  385.     } else {
  386.     argc -= optind;
  387.     argv += optind;
  388.     }
  389.  
  390.     if (term == 0 || *term == '\0')
  391.     quit(2, "No value for $TERM and no -T specified");
  392.  
  393.     if (setupterm(term, STDOUT_FILENO, &errret) != OK && errret <= 0)
  394.     quit(3, "unknown terminal \"%s\"", term);
  395.  
  396.     if (cmdline) {
  397.     if ((argc <= 0) && !is_reset && !is_init)
  398.         usage();
  399.     return tput(argc, argv);
  400.     }
  401.  
  402.     while (fgets(buf, sizeof(buf), stdin) != 0) {
  403.     char *argvec[16];    /* command, 9 parms, null, & slop */
  404.     int argnum = 0;
  405.     char *cp;
  406.  
  407.     /* crack the argument list into a dope vector */
  408.     for (cp = buf; *cp; cp++) {
  409.         if (isspace(UChar(*cp))) {
  410.         *cp = '\0';
  411.         } else if (cp == buf || cp[-1] == 0) {
  412.         argvec[argnum++] = cp;
  413.         if (argnum >= (int) SIZEOF(argvec) - 1)
  414.             break;
  415.         }
  416.     }
  417.     argvec[argnum] = 0;
  418.  
  419.     if (argnum != 0
  420.         && (err = tput(argnum, argvec)) != 0) {
  421.         if (result == 0)
  422.         result = 4;    /* will return value >4 */
  423.         ++result;
  424.     }
  425.     }
  426.  
  427.     return result;
  428. }
  429.